﻿// ------------------------------------------------------------------------
// 版权信息
// 版权归重庆虫儿飞科技有限公司所有。
// 所有权利保留。
// 官方网站：https://netokit.com
// 许可证信息
// Neto.Kit 项目主要遵循 MIT 许可证和 Apache 许可证（版本 2.0）进行分发和使用。
// 许可证的完整文本可以在源代码树根目录中的 LICENSE-APACHE 和 LICENSE-MIT 文件中找到。
// 
// 使用条款
// 使用本代码应遵守相关法律法规和许可证的要求。
// 
// 免责声明
// 对于因使用本代码而产生的任何直接、间接、偶然、特殊或后果性损害，我们不承担任何责任。
// 
// 其他重要信息
// Neto.Kit 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。
// 有关 Neto.Kit 项目的其他详细信息，请参阅位于源代码树根目录中的 COPYRIGHT 和 DISCLAIMER 文件。
// 
// 更多信息
// 请访问 https://netokit.com 获取更多关于 Neto.Kit 项目的许可证和版权信息。
// ------------------------------------------------------------------------

#region

using Microsoft.Extensions.Hosting;
using Serilog;
using Serilog.Events;
using ILogger = Serilog.ILogger;

#endregion

/// <summary>
///     Serilog扩展
/// </summary>
public static class SerilogExtension
{
    // /// <summary>
    // ///     设置ES基础安全认证
    // /// </summary>
    // /// <param name="conn"></param>
    // /// <param name="_esLogConfigOptions"></param>
    // internal static void SetBasicAuthentication(ConnectionConfiguration conn,
    //     EsLoggingConfigOptions _esLogConfigOptions)
    // {
    //     if (!string.IsNullOrWhiteSpace(_esLogConfigOptions.AuthUserName) &&
    //         !string.IsNullOrWhiteSpace(_esLogConfigOptions.AuthPassword))
    //         // 使用环境变量或加密的凭据来代替硬编码的用户名和密码
    //         conn.BasicAuthentication(_esLogConfigOptions.AuthUserName, _esLogConfigOptions.AuthPassword);
    // }

    /// <summary>
    ///     添加SerilogTo Es日志拓展
    /// </summary>
    /// <param name="builder"></param>
    /// <param name="isWriteFileLog">是否写入文件日志,默认false</param>
    /// <param name="configAction"></param>
    /// <returns></returns>
    public static IHostBuilder UseSerilogToEs(this IHostBuilder builder, bool isWriteFileLog = true,
        Action<LoggerConfiguration> configAction = null)
    {
        var isSingleFileEnvironment = string.IsNullOrWhiteSpace(Assembly.GetEntryAssembly()!.Location);
        builder.UseSerilog(delegate(HostBuilderContext context, LoggerConfiguration configuration)
        {
            //var _esLogConfigOptions = AppX.GetConfig<EsLoggingConfigOptions>();

            #region Es日志
            //
            // //配置了ES Log才执行
            // if (_esLogConfigOptions != null && _esLogConfigOptions.IsEanble && _esLogConfigOptions.Urls != null &&
            //     _esLogConfigOptions.Urls.Any())
            // {
            //     var uris = _esLogConfigOptions.Urls?.Select(o => new Uri(o)) ?? new List<Uri>();
            //
            //     //string environment = "Development";
            //     configuration
            //         .ReadFrom.Configuration(context.Configuration)
            //         .Enrich.FromLogContext()
            //         //过滤Net Core系统日志
            //         .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
            //         .WriteTo.Console()
            //         .WriteTo.Elasticsearch(new ElasticsearchSinkOptions(uris)
            //         {
            //             //OverwriteTemplate和TypeName一定要加，不然ES8无法写入日志
            //
            //             IndexFormat = _esLogConfigOptions.DefaultIndex, //默认索引名称
            //             //IndexFormat = $"{Assembly.GetExecutingAssembly().GetName().Name.ToLower().Replace(".", "-")}-{environment?.ToLower().Replace(".", "-")}-{DateTime.UtcNow:yyyy-MM}",
            //             AutoRegisterTemplate = true, //是否ES日志自动注册一个索引模板。
            //             OverwriteTemplate = true, //是否覆盖ES日志默认模板，ES8默认不支持写入，需要加此配置
            //             //TemplateName = "",//ES日志模板
            //             FailureCallback = (logevent, e) =>
            //             {
            //                 Console.WriteLine($"LogEvent:{logevent.Level:G} : Unable to submit event " + e.Message);
            //             }, //日志发送失败触发事件
            //             AutoRegisterTemplateVersion = AutoRegisterTemplateVersion.ESv8, //ES模板版本
            //             TypeName = null, //ES8默认不支持写入，需要加此配置
            //             MinimumLogEventLevel = LogEventLevel.Verbose, //最低日志等级
            //             EmitEventFailure = EmitEventFailureHandling.RaiseCallback, //设置了当失败时调用FailureCallback
            //             BatchAction = ElasticOpType.Create,
            //             BatchPostingLimit = 50, //一次批量发送日志数量，默认50
            //             //ES认证，用户登录+是否开启SSL(Https)
            //             ModifyConnectionSettings =
            //                 conn =>
            //                 {
            //                     //conn.BasicAuthentication("elastic", "123456");
            //                     SetBasicAuthentication(conn, _esLogConfigOptions); //设置基础安全认证
            //                     conn.ServerCertificateValidationCallback((source, certificate, chain,
            //                         sslPolicyErrors) => false);
            //                     return conn;
            //                 }
            //         });
            // }

            #endregion Es日志

            #region 文件日志

            //如果打开了写文件日志或未配置的eslog
            //if (isWriteFileLog || _esLogConfigOptions == null)
            if (isWriteFileLog)
            {
                var loggerConfiguration =
                    configuration.ReadFrom.Configuration(context.Configuration).Enrich.FromLogContext();
                if (configAction != null)
                    configAction(loggerConfiguration);
                else
                    SerilogX.SetDefaultConfiguration(loggerConfiguration);
                //else if (context.Configuration["Serilog:WriteTo:0:Name"] == null)
                //{
                //    loggerConfiguration.WriteTo.Console(LogEventLevel.Verbose, "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} {Properties:j}{NewLine}{Exception}").WriteTo.File(Path.Combine((!isSingleFileEnvironment) ? AppDomain.CurrentDomain.BaseDirectory : AppContext.BaseDirectory, "logs", "application..log"), LogEventLevel.Information, "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}", null, retainedFileCountLimit: null, encoding: Encoding.UTF8, fileSizeLimitBytes: 1073741824L, levelSwitch: null, buffered: false, shared: false, flushToDiskInterval: null, rollingInterval: RollingInterval.Day);
                //}
            }

            #endregion 文件日志
        });
        return builder;
    }

    /// <summary>
    ///     添加SerilogTo Es日志拓展
    /// </summary>
    /// <param name="builder"></param>
    /// <param name="isWriteFileLog">是否写入文件日志,默认false</param>
    /// <param name="configAction"></param>
    /// <returns></returns>
    public static WebApplicationBuilder UseSerilogToEs(this WebApplicationBuilder builder, bool isWriteFileLog = false,
        Action<LoggerConfiguration> configAction = null)
    {
        builder.Host.UseSerilogToEs(isWriteFileLog, configAction);
        return builder;
    }

    #region Serilog扩展

    /// <summary>
    ///     调试日志
    /// </summary>
    /// <param name="logger"></param>
    /// <param name="ex"></param>
    public static void Debug(this ILogger logger, Exception ex)
    {
        logger.Debug(ex.ToStringEx());
    }

    /// <summary>
    ///     错误日志
    /// </summary>
    /// <param name="logger"></param>
    /// <param name="ex"></param>
    public static void Error(this ILogger logger, Exception ex)
    {
        logger.Error(ex.ToStringEx());
    }

    /// <summary>
    ///     致命日志
    /// </summary>
    /// <param name="logger"></param>
    /// <param name="ex"></param>
    public static void Fatal(this ILogger logger, Exception ex)
    {
        logger.Fatal(ex.ToStringEx());
    }

    /// <summary>
    ///     信息日志
    /// </summary>
    /// <param name="logger"></param>
    /// <param name="msg"></param>
    public static void Info(this ILogger logger, string msg)
    {
        logger.Information(msg);
    }

    /// <summary>
    ///     信息日志
    /// </summary>
    /// <param name="logger"></param>
    /// <param name="ex"></param>
    public static void Info(this ILogger logger, Exception ex)
    {
        logger.Information(ex.ToStringEx());
    }

    /// <summary>
    ///     冗余日志
    /// </summary>
    /// <param name="logger"></param>
    /// <param name="ex"></param>
    public static void Verbose(this ILogger logger, Exception ex)
    {
        logger.Verbose(ex.ToStringEx());
    }

    /// <summary>
    ///     冗余日志
    /// </summary>
    /// <param name="logger"></param>
    /// <param name="ex"></param>
    public static void Trace(this ILogger logger, Exception ex)
    {
        logger.Verbose(ex.ToStringEx());
    }

    /// <summary>
    ///     警告日志
    /// </summary>
    /// <param name="logger"></param>
    /// <param name="ex"></param>
    public static void Warning(this ILogger logger, Exception ex)
    {
        logger.Warning(ex.ToStringEx());
    }

    #endregion
}